package home

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

const s_width = 21 // MUST % 3 == 0
const s_mask_0 = uint32(0o_111_111_111 & (^uint32(0) >> (32 - s_width)))
const s_mask_1 = uint32(0o_222_222_222 & (^uint32(0) >> (32 - s_width)))
const s_mask_2 = uint32(0o_444_444_444 & (^uint32(0) >> (32 - s_width)))
const s_for_cnt = (1 << s_width)

var threshold_s1 = 0

func sp1_out_file(fileName string) *bufio.Writer {
	path := "../tmp/" + fileName
	dir := filepath.Dir(path)

	// Ensure directory exists
	if err := os.MkdirAll(dir, os.ModePerm); err != nil {
		fmt.Println("Fail to create directory:", err)
		return nil
	}

	file, err := os.Create(path)
	if err != nil {
		fmt.Println("Fail to create file:", err)
		return nil
	}

	writer := bufio.NewWriter(file)
	bufferSize := writer.Available()
	threshold_s1 = bufferSize / 2

	// Optional: background flush ticker
	go func() {
		ticker := time.NewTicker(10 * time.Second)
		defer ticker.Stop()
		for range ticker.C {
			if writer.Buffered() >= threshold_s1 {
				writer.Flush()
			}
		}
	}()

	return writer
}

func sp1_circle_f(writer *bufio.Writer, fn func(nf int) int) {
	var tm = Bitmap{}
	tm.Init(s_for_cnt + 1)
	var bm = Bitmap{}
	bm.Init(s_for_cnt + 1)

	// fmt.Printf("%20b,%20b,%20b", s_mask_0, s_mask_1, s_mask_2)

	writer.WriteString("[")

	for i := 0; i <= s_for_cnt; i++ {
		if tm.Test(i) {
			continue
		}

		bm.ClearAll()
		n, c := i, 0

		for !bm.Test(n) {
			bm.Set(n)
			tm.Set(n)
			n = fn(n)

			// fmt.Printf("%20b", n)

			// Ensure n stays within valid range
			// if n > s_for_cnt {
			// 	fmt.Println("Invalid n value:", n)
			// 	break
			// }

			c++
		}

		if c <= 1<<6 {
			continue
		}

		writer.WriteString("{i:")
		writer.WriteString(strconv.Itoa(i))
		writer.WriteString(",c:")
		writer.WriteString(strconv.Itoa(c))
		writer.WriteString("},")

		if writer.Buffered() >= threshold_s1 {
			writer.Flush()
		}

	}
	// 我想在这里删除末尾的逗号，writer.WriteString竟然实现不了
	writer.WriteString("]")
	writer.Flush()
}

func sp1_c_t(n int) int {

	ns := uint32(n)
	t2 := (s_mask_2 & ns) >> 2
	b1 := (s_mask_1 & ns) >> 1
	b0 := s_mask_0 & ns

	// return ((t2 ^ b1 ^ b0) << 2) | ((t2 & b0) << 1) | (t2 | b1)
	return int((t2 << 2) | ((t2 & b0) << 1) | (t2 | b1))
}

func sp1_c_b(n int) int {

	ns := uint32(n)
	t2 := (s_mask_2 & ns) >> 2
	b1 := (s_mask_1 & ns) >> 1
	b0 := s_mask_0 & ns

	// return ((t2 ^ b1 ^ b0) << 2) | ((t2 & b0) << 1) | (t2 | b1)
	return int(((t2 ^ b1 ^ b0) << 2) | (b1 << 1) | (b0))
}
